package red.mlz.app.controller.game;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import red.mlz.app.domain.BaseDescriptionValueVo;
import red.mlz.app.domain.game.GameInfoVo;
import red.mlz.app.domain.game.GameItemVo;
import red.mlz.app.domain.game.GameListVo;
import red.mlz.app.domain.game.GameWpVo;
import red.mlz.module.module.category.entity.Category;
import red.mlz.module.module.category.service.CategoryService;
import red.mlz.module.module.game.entity.Game;
import red.mlz.module.module.game.service.GameService;
import red.mlz.module.module.gametagrelation.entity.GameTagRelation;
import red.mlz.module.module.gametagrelation.service.GameTagRelationService;
import red.mlz.module.module.tag.service.TagService;
import red.mlz.module.utils.BaseUtils;
import red.mlz.module.utils.ImageUtils;
import red.mlz.module.utils.Response;
import red.mlz.module.utils.SpringUtils;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@Slf4j
public class GameController {
    @Autowired
    private GameService gameService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private GameTagRelationService gameTagRelationService;
    @Autowired
    private TagService tagService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @RequestMapping("/game/list")
    public Response getGameList(@RequestParam(required = false) String wp,
                              @RequestParam(required = false) String keyword) {

        String cacheKey = buildCacheKey(wp, keyword);

        GameListVo cacheResult = (GameListVo) redisTemplate.opsForValue().get(cacheKey);
        if (cacheResult != null) {
            return new Response(1001,cacheResult);
        }

        try {
            // 解析 wp 参数
            GameWpVo baseWp = new GameWpVo();
            if (!BaseUtils.isEmpty(wp)) {
                byte[] bytes = Base64.getUrlDecoder().decode(wp.getBytes(StandardCharsets.UTF_8));
                String realWp = new String(bytes, StandardCharsets.UTF_8);
                try {
                    baseWp = JSON.parseObject(realWp, GameWpVo.class);
                }catch (Exception e){
                    return new Response(4004,e.getMessage());
                }
            }else {
                baseWp.setPage(1);
                baseWp.setKeyword(keyword);
            }

            String pageSize = SpringUtils.getProperty("application.pageSize");

            List<Game> games = gameService.getAllGames(baseWp.getPage(), Integer.parseInt(pageSize), baseWp.getKeyword());
            Boolean isEnd = games.size() < Integer.parseInt(pageSize);
            // 收集所有categoryId
            List<Long> categoryIds = games.stream()
                    .map(Game::getCategoryId)
                    .distinct()
                    .collect(Collectors.toList());

            // 批量查询分类信息
            List<Category> categories = categoryService.listByIds(categoryIds);
            Map<Long, Category> categoryMap = categories.stream()
                    .collect(Collectors.toMap(Category::getId, Function.identity()));

            List<GameItemVo> gameItems = games.stream()
                    .map(game -> {
                        GameItemVo itemVO = new GameItemVo();
                        itemVO.setId(game.getId());
                        // 处理图片信息
                        GameItemVo.ImageInfo imageInfo = new GameItemVo.ImageInfo();
                        String imageUrl = game.getCoverImages();

                        // 处理图片URL
                        if (imageUrl != null && !imageUrl.isEmpty()) {
                            // 设置原图URL（去掉参数保留基础地址）
                            imageInfo.setUrl(imageUrl.split("\\?")[0]);
                            // 从文件名提取宽高比
                            Float aspectRatio = ImageUtils.parseAspectRatio(imageUrl);
                            imageInfo.setAr(String.valueOf(aspectRatio));
                        } else {
                            // 设置默认图片URL和宽高比
                            imageInfo.setUrl("");
                            imageInfo.setAr("1.0");
                        }

                        itemVO.setImage(imageInfo);
                        itemVO.setGameName(game.getGameName());
                        itemVO.setPlayerNumber(game.getPlayerNumber());
                        Long categoryId = game.getCategoryId();
                        Category category = categoryMap.get(categoryId);
                        if (category != null) {
                            itemVO.setCategoryName(category.getName());
                        } else {
                            // 处理分类不存在的情况
                            itemVO.setCategoryName("未知分类");
                        }
                        return itemVO;
                    })
                    .collect(Collectors.toList());

            GameWpVo nextWPParam = new GameWpVo();
            nextWPParam.setPage(baseWp.getPage()+1);     // 下一页
            nextWPParam.setKeyword(keyword);   // 透传当前 keyword
            String nextWP;
            try {
                // 1. JSON序列化
                String jsonStr = JSON.toJSONString(nextWPParam);

                // 2. Base64 URL安全编码
                byte[] encodedBytes = Base64.getUrlEncoder()
                        .withoutPadding()  // 去掉末尾填充符
                        .encode(jsonStr.getBytes(StandardCharsets.UTF_8));

                nextWP = new String(encodedBytes, StandardCharsets.UTF_8);
            } catch (Exception e) {
                // 编码失败时返回空参数或默认值
                nextWP = "";
            }

            GameListVo result = new GameListVo();
            result.setList(gameItems);
            result.setIsEnd(isEnd);
            result.setWp(nextWP);
            redisTemplate.opsForValue().set(cacheKey, result, 1, TimeUnit.HOURS);

            return new Response(1001,result);
        } catch (Exception e) {
            return new Response(4004, e.getMessage());
        }
    }

    //根据wp和keyword参数生成唯一的缓存Key
    private String buildCacheKey(String wp, String keyword) {
        if (!BaseUtils.isEmpty(wp)) {
            return "game_list:wp:" + wp + ":keyword:" + (keyword != null ? keyword : "");  // wp存在时，Key基于wp参数
        } else {
            // wp不存在时，Key基于keyword（处理null和空值）
            return "game_list:keyword:" + (keyword != null ? keyword : "");
        }
    }

    @RequestMapping("/game/info")
    public Response getGameInfo(@RequestParam Long gameId) {
        Game game = gameService.getById(gameId);

        if (BaseUtils.isEmpty(game)) {
            return new Response(4004);
        }

        Category category = categoryService.getById(gameId);
        String categoryName = category != null ? category.getName() : null;
        String categoryImage = category != null ? category.getImage() : null;

        GameInfoVo result = new GameInfoVo();
        result.setTitle(game.getTitle());
        result.setCreateTime(game.getCreateTime());
        result.setCoverImages(game.getCoverImages());
        result.setGameName(game.getGameName());
        result.setReleaseDate(game.getReleaseDate());
        result.setPrice(game.getPrice());
        try {
            List<BaseDescriptionValueVo> descriptions = JSON.parseArray(game.getGameDescription(), BaseDescriptionValueVo.class);
            result.setGameDescription(descriptions);
        }catch (Exception cause){
            return new Response(4004);
        }
        // 查询游戏标签
        List<GameTagRelation> relations = gameTagRelationService.findByGameId(gameId);
        List<String> tags = relations.stream()
                .map(relation -> tagService.getById(relation.getTagId()).getName())
                .collect(Collectors.toList());

        result.setTags(tags);
        result.setRating(game.getRating());
        result.setCategoryName(categoryName);
        result.setCategoryImage(categoryImage);

        return new  Response(1001,result);
    }

}
